
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Scanner;

class Function {
    String date; // YYYY-MM-DD
    double amount;//数量
    String category;//类别
    String note;//日期

    public Function(String date, double amount, String category, String note) {
        this.date = date;
        this.amount = amount;
        this.category = category;
        this.note = note;
    }
}

public class FinanceManager {
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    private static ArrayList<Function> incomeRecords = new ArrayList<>();
    private static ArrayList<Function> expenseRecords = new ArrayList<>();

    // 预算管理
    static double monthlyBudget = 0.0;  // 每月预算
    static double remainingBudget = 0.0; // 剩余预算

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        while (true) {
            System.out.println("=======================");
            System.out.println("欢迎使用个人账单管理系统");
            System.out.println("=======================");
            System.out.println("1. 记录收入");
            System.out.println("2. 记录支出");
            System.out.println("3. 查看所有账单");
            System.out.println("4. 查询账单");
            System.out.println("5. 设置月度预算");
            System.out.println("6. 查看月度统计报告");
            System.out.println("7. 退出系统");


            System.out.print("请输入选项序号: ");
            int choice = scanner.nextInt();
            scanner.nextLine(); // 清空输入缓冲区

            switch (choice) {
                case 1:
                    addIncome();
                    break;
                case 2:
                    addExpense();
                    break;
                case 3:
                    viewRecordsAndSummary(incomeRecords,expenseRecords);
                    break;
                case 4:
                    searchRecords();
                    break;
                case 5:
                    setBudget();
                    break;
                case 6:
                    getMonthlyStatistics();
                    break;
                case 7:
                    System.out.println("感谢使用个人账单管理系统！");
                    scanner.close();
                    return;
                default:
                    System.out.println("无效的选择，请重试！");
            }
        }
    }

    private static void addIncome() {
        boolean validDate = false;
        String date = scanner.nextLine();
        while (!validDate) {
            System.out.print("请输入日期 (YYYY-MM-DD): ");
            try {
                // 尝试解析输入的日期
                dateFormat.setLenient(false); // 禁用宽松模式，严格按照日期格式解析
                dateFormat.parse(date); // 如果解析成功，日期格式是有效的
                validDate = true; // 日期有效，跳出循环
            } catch (ParseException e) {
                // 捕捉到解析异常，提示用户重新输入
                System.out.println("日期格式错误，请使用 YYYY-MM-DD 格式！");
            }
        }

        System.out.print("请输入收入金额: ");
        double amount = scanner.nextDouble();
        if (amount <= 0) {
            System.out.println("收入金额必须为正数！");
            return;//用于判断收入金额是否为正数
        }
        scanner.nextLine(); // 清空输入缓冲区
        System.out.print("请输入类别: ");
        String category = scanner.nextLine();
        System.out.print("请输入备注: ");
        String note = scanner.nextLine();

        incomeRecords.add(new Function(date, amount, category, note));
        System.out.println("收入记录添加成功！");
    }

    private static void addExpense() {
        boolean validDate = false;
        String date = scanner.nextLine();
        while (!validDate) {
            System.out.print("请输入日期 (YYYY-MM-DD): ");
            try {
                // 尝试解析输入的日期
                dateFormat.setLenient(false); // 禁用宽松模式，严格按照日期格式解析
                dateFormat.parse(date); // 如果解析成功，日期格式是有效的
                validDate = true; // 日期有效，跳出循环
            } catch (ParseException e) {
                // 捕捉到解析异常，提示用户重新输入
                System.out.println("日期格式错误，请使用 YYYY-MM-DD 格式！");
            }
        }
        System.out.println("请输入支出金额：");
        double amount = scanner.nextDouble();
        if (amount <= 0) {
            System.out.println("支出金额必须为正数！");
            return;
        }
        scanner.nextLine();
        System.out.print("请输入类别: ");
        String category = scanner.nextLine();
        System.out.print("请输入备注: ");
        String note = scanner.nextLine();

        expenseRecords.add(new Function(date, amount, category, note));
        System.out.println("支出记录添加成功！");

        // 检查是否超过预算
        if (monthlyBudget > 0 && remainingBudget < amount) {
            System.out.println("警告：支出超过剩余预算！当前剩余预算: " + remainingBudget);
        } else {
            expenseRecords.add(new Function(date, amount, category, note));
            remainingBudget -= amount; // 更新剩余预算
            System.out.println("支出记录成功！当前剩余预算: " + remainingBudget);
        }
    }

    public static void viewRecordsAndSummary(ArrayList<Function> incomeRecords, ArrayList<Function> expenseRecords) {
        // 显示收入记录
        if (incomeRecords.isEmpty()) {
            System.out.println("收入记录为空！");
        } else {
            System.out.println("收入记录：");
            for (Function record : incomeRecords) {
                System.out.println(record);
            }
        }

        // 显示支出记录
        if (expenseRecords.isEmpty()) {
            System.out.println("支出记录为空！");
        } else {
            System.out.println("支出记录：");
            for (Function record : expenseRecords) {
                System.out.println(record);
            }
        }

        // 汇总收入和支出
        double totalIncome = incomeRecords.stream().mapToDouble(record -> record.amount).sum();
        double totalExpense = expenseRecords.stream().mapToDouble(record -> record.amount).sum();
        double balance = totalIncome - totalExpense;

        System.out.printf("总收入: %.2f, 总支出: %.2f, 余额: %.2f%n", totalIncome, totalExpense, balance);
    }

    private static void searchRecords() {
        System.out.println("选择查询方式:");
        System.out.println("1. 按日期查询");
        System.out.println("2. 按日期范围查询");
        System.out.println("3. 按类别查询");
        System.out.print("请输入你的选择: ");
        int searchChoice = scanner.nextInt();
        scanner.nextLine(); // 清空输入缓冲区

        switch (searchChoice) {
            case 1:
                System.out.print("请输入日期 (YYYY-MM-DD): ");
                String date = scanner.nextLine();
                viewRecordsByDate(date);
                break;
            case 2:
                System.out.print("请输入开始日期 (YYYY-MM-DD): ");
                String startDate = scanner.nextLine();
                System.out.print("请输入结束日期 (YYYY-MM-DD): ");
                String endDate = scanner.nextLine();
                viewRecordsByDateRange(startDate, endDate);
                break;
            case 3:
                System.out.print("请输入类别: ");
                String category = scanner.nextLine();
                viewRecordsByCategory(category);
                break;
            default:
                System.out.println("无效的选择，请重试！");
        }
    }

    private static void viewRecordsByDate(String date) {
        System.out.println("收入记录:");
        incomeRecords.stream()
                .filter(record -> record.date.equals(date))
                .forEach(record -> System.out.printf("%s | %.2f | %s | %s%n", record.date, record.amount, record.category, record.note));

        System.out.println("支出记录:");
        expenseRecords.stream()
                .filter(record -> record.date.equals(date))
                .forEach(record -> System.out.printf("%s | %.2f | %s | %s%n", record.date, record.amount, record.category, record.note));
    }

    private static void viewRecordsByDateRange(String startDate, String endDate) {
        System.out.println("收入记录:");
        incomeRecords.stream()
                .filter(record -> record.date.compareTo(startDate) >= 0 && record.date.compareTo(endDate) <= 0)
                .forEach(record -> System.out.printf("%s | %.2f | %s | %s%n", record.date, record.amount, record.category, record.note));

        System.out.println("支出记录:");
        expenseRecords.stream()
                .filter(record -> record.date.compareTo(startDate) >= 0 && record.date.compareTo(endDate) <= 0)
                .forEach(record -> System.out.printf("%s | %.2f | %s | %s%n", record.date, record.amount, record.category, record.note));
    }

    private static void viewRecordsByCategory(String category) {
        System.out.println("收入记录:");
        incomeRecords.stream()
                .filter(record -> record.category.equals(category))
                .forEach(record -> System.out.printf("%s | %.2f | %s | %s%n", record.date, record.amount, record.category, record.note));

        System.out.println("支出记录:");
        expenseRecords.stream()
                .filter(record -> record.category.equals(category))
                .forEach(record -> System.out.printf("%s | %.2f | %s | %s%n", record.date, record.amount, record.category, record.note));
    }

    // 设置预算
    public static void setBudget() {
        System.out.print("请输入每月预算金额: ");
        monthlyBudget = scanner.nextDouble();
        remainingBudget = monthlyBudget;  // 设置预算后，剩余预算即为预算金额
        System.out.println("月度预算已设置为: " + monthlyBudget);
        System.out.println("当前剩余预算: " + remainingBudget);
    }

    // 获取月度统计 (按月统计收入和支出)
    public static void getMonthlyStatistics() {
        System.out.print("请输入查询的月份 (格式: yyyy-MM): ");
        String month = scanner.nextLine();

        double totalIncome = 0;
        double totalExpense = 0;

        for (Function record : incomeRecords) {
            if (record.date.startsWith(month)) {
                totalIncome += record.amount;
            }
        }

        for (Function record : expenseRecords) {
            if (record.date.startsWith(month)) {
                totalExpense += record.amount;
            }
        }

        System.out.println(month + " 月度统计：");
        System.out.println("总收入: " + totalIncome);
        System.out.println("总支出: " + totalExpense);
        System.out.println("余额: " + (totalIncome - totalExpense));
    }


}
